/**
 * 
 */
package ProtoSimulator;

import java.io.*;
import java.net.*;
import java.lang.Thread;
import java.net.URL;
import java.util.HashMap;
import java.util.Random;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.Transport;

import org.apache.log4j.Logger;

/**
 * @author jjmb
 *
 */
public class NotificationHandler extends Thread {
	private static final String CLASS_NAME = NotificationHandler.class.getName();
    public static final Logger logger = Logger.getLogger(CLASS_NAME);
    
    private static Properties mailProperties = new Properties();
    private static Session session;
    private static Message mailMessage;
    private static String mailAddresses = null;
    private static String mailFrom = null;
    private static String mailFromPassword = null;
    private static String mailSubject = null;
    private static Address mailRecipients = null;
    private static HashMap notficationsHash = null;
    private static Notification notification = null;
    private static Iterator iterator = null;
    private static Set entry = null;
    private static int notificationCount = 0;
    private static Transport mailTransport = null;
    	
    public NotificationHandler(Notification n, Properties p) {
    	// processing notification object
    	notification = n;
    	
    	// retrieving properties and setting variables
    	if(p.get("NotificationMailHost") != null) {
    		mailProperties.put("mail.smtp.host", p.getProperty("NotificationMailHost"));
    		mailProperties.put("mail.smtp", true);
    		mailProperties.put("mail.smtp.starttls.enable", true);
    		logger.trace("mail.smtp.host set to " + mailProperties.get("mail.smtp.host"));
    	}
    	
    	if(p.get("NotificationEmailAddresses") != null) {
    		mailAddresses = p.getProperty("NotificationEmailAddresses");
    		logger.trace("mailAddresses set to " + mailAddresses);
    	}
    	
    	if(p.get("NotificationMailFrom") != null) {
    		mailFrom = p.getProperty("NotificationMailFrom");
    		logger.trace("mailFrom set to " + mailFrom);
    	}
    	
    	if(p.get("NotificationMailFromPassword") != null) {
    		mailFromPassword = p.getProperty("NotificationMailFromPassword");
    		logger.trace("mailFromPassword set to <Not Displayed>");
    	}
    	
    	if(p.get("NotificationMailSubject") != null) {
    		mailSubject = p.getProperty("NotificationMailSubject");
    		logger.trace("mailSubject set to " + mailSubject);
    	}
    	
    	// Creating session
    	Session mailSession = Session.getInstance(mailProperties);
    	    	
    	try {
    		mailMessage = new MimeMessage(mailSession);
    		mailMessage.setFrom(new InternetAddress(mailFrom));
    		mailRecipients = new InternetAddress(mailAddresses);
    		// mailMessage.addRecipient(Message.RecipientType.TO, mailRecipients);
    		mailMessage.setRecipient(Message.RecipientType.TO, mailRecipients);
    		mailMessage.setSubject(mailSubject);
    		mailTransport = mailSession.getTransport("smtp");
    	}
    	catch(Exception e) {
    		logger.fatal(e);
    	}
    }
   
    public NotificationHandler(Notification n) {
    }
	
    public void run() {
    	logger.info("Starting NotificationHandler...");
    	// TODO Notification Handler processing
    	// for(;;) {
    	while(notification.hasNotifications()) {
    		notificationCount = notification.getNotificationCount();
    		if(notificationCount > 0) {
    			logger.debug("Notification count is greater than zero, " + notificationCount);
    			notficationsHash = (HashMap) notification.getAllNotifications();
    			logger.trace("Dump of notification hash table, " + notficationsHash.toString());
    			entry = notficationsHash.entrySet();
    			logger.trace("Dump of entry, " + entry.toString());
    			iterator = entry.iterator();
    			while(iterator.hasNext()) {
    				Map.Entry tmp = (Map.Entry) iterator.next();
    				logger.trace("Processing notification ID = " + tmp.getKey() + " with message " + tmp.getValue());
    				try {
    					logger.debug("Preparing to send message, " + tmp.getValue().toString());
        				mailMessage.setContent(tmp.getValue().toString(), "text/plain");
        				logger.trace("Content of message set to " + mailMessage.getContent().toString() + " with type " + mailMessage.getContentType().toString());
        				/**
        				if(mailFrom.length() <= 0) {
        						logger.trace("Mail from has a length of 0 or less");
        				}
        				else {
        					logger.trace("Mail from is " + mailFrom);
        				}
        				if(mailFromPassword.length() <= 0) {
    						logger.trace("Mail from password has a length of 0 or less");
        				}
        				else {
        					logger.trace("Mail from passsword is " + mailFromPassword);
        				}
        				**/
        				
        				if(mailTransport == null) {
        					logger.trace("Mail transport is null");
        				}
        				else {
        					logger.trace("Mail transport is not null");
        				}
        				if(mailTransport.isConnected()) {
        					logger.trace("Transported is not connected.");
        				} 
        				else {
        					logger.trace("Mail transport is connected");
        				}
        				mailTransport.connect(mailFrom, mailFromPassword);
        				// logger.trace("Connected to mail server successfully.");
        				mailTransport.sendMessage(mailMessage, mailMessage.getAllRecipients());
        				logger.trace("Message sent successfully.");
        				/**
        				mailTransport.close();
        				logger.trace("Closed transport successfully.");
        				**/
        				logger.debug("Deleting sent notification with ID, " + tmp.getKey().hashCode());
        				notification.deleteNotification(tmp.getKey().hashCode());
    				}
    				catch (Exception e) {
    					logger.fatal(e);
    				}
    			}
    		}
    		/**
    		else {
    			// logger.trace("Sleeping...");
    			try {
    				Thread.sleep(100);	
    				logger.trace("Sleeping for 100ms...");
    			} 
    			catch(Exception e) {
    				logger.fatal(e);
    			}
    			// continue;
    		}
    		**/
    		// TODO leverage sleep here to control main loop
    		/**
    		try {
    			Thread.sleep(100);
    		}
			catch(Exception e) {
				logger.fatal(e);
			}
			**/
    	}
    }
}
